home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
C/C++ Users Group Library 1996 July
/
C-C++ Users Group Library July 1996.iso
/
vol_100
/
133_01
/
textcom
< prev
next >
Wrap
Text File
|
1985-03-09
|
12KB
|
496 lines
/*
CUG-HEADER:
TITLE: "Text comparison utility"
VER: 1.7
AUTHOR: G.N. GILBERT
O.S.: CP/M 2.2
FNAME: TEXTCOM
DESC: compares two text files, printing differences
attempts to re-synchronise after finding differences
KEYWORDS: text, differences
*/
/*
TEXTCOM
compares two text files, printing differences
attempts to synchronise after finding differences.
G. Nigel Gilbert / MICROLOGY (tel 04868-22521) 16.10.81
vers 1.3: tabs expanded on list output 30.8.82
vers 1.4: control chars suppressed on output (except ^I,cr/lf)
vers 1.5: option to ignore parity bit
vers 1.6: findline() substituted for fgets(), which got screwed
up when \n had its parity bit set
vers 1.7: option to match white space in comparison
compile with -e3300 -o
*/
#define VERSION 17
#include <bdscio.h>
#define MAXINT 65535
#define MAXSYNC 100 /*max distance to attempt to restore synchronism*/
#define DEFLSYNC 3 /*default no. of bytes which must match to
establish synchronity*/
#define MAXLEN 512 /*max length of input line*/
#define NO 0
#define YES 1
#define bool char
bool putboth; /*print diffs on both screen and printer*/
bool pause; /*stop at the end of each screen of output*/
bool nosync; /*don't attempt to synchronise*/
int sync; /*distance over which files must be matched */
int line; /*output line count*/
int col; /*output column no for printer tabs*/
bool report; /*write differences to file*/
bool parity; /*ignore parity bit*/
bool white; /*match white space*/
char repbuf[BUFSIZ]; /*file buffer for report*/
char name1[15], name2[15]; /*names of files to compare*/
unsigned line1, line2; /*line counts for input files*/
unsigned start, stop; /*start and stop comparing at lines..*/
bool different, listing;/*found a difference; list diffs.*/
char *c1,*c2; /*pointers to current lines being compared*/
char fbuf1[BUFSIZ], fbuf2[BUFSIZ]; /*input file buffers*/
char repname[15]; /*report file name*/
struct aring {
char *buf[MAXSYNC];
int ringp;
bool eof;
}
ring1, ring2; /*file input ring buffer*/
char *findline(line,iobuf) /*read a line from an input file, stripping
'\n', and returning NULL if at Eof */
char *line, *iobuf;
{
int cint;
char i, cnopar;
for (i=0; i < (MAXLEN-1) && (cint=getc(iobuf)) != ERROR; i++) {
if ((cnopar=cint & 0x7f) == CPMEOF) return NULL;
if (cnopar == '\n') break;
if (cnopar == '\r') continue;
*line++= (parity ? cnopar : cint);
}
*line='\0';
return line;
}
char *readline(iobuf) /*read a line and store it away, returning pointer
to it, or NULL if end of file*/
char *iobuf;
{
char temp[MAXLEN], *t, *p, *alloc(), *findline(), *strcpy();
if (findline(temp,iobuf) == NULL) return NULL;
if ((p=alloc(strlen(temp)+1)) == NULL) {
puts("Out of memory\n");
exit();
}
return strcpy(p,temp);
}
char *getline(ring,iobuf) /*get a line of text from ring buffer
returning pointer to it;
replace with one from input file*/
struct aring *ring;
char *iobuf;
{
char *c, **p, *readline();
if (ring -> ringp == MAXSYNC) ring -> ringp = 0;
c = *( p=&(ring -> buf[ring -> ringp++]) );
if (ring -> eof || (*p=readline(iobuf)) == NULL) {
*p=EOF;
ring -> eof=YES;
}
return c;
}
initring(ring,iobuf) /*initialise by filling ring buffer*/
struct aring *ring;
char *iobuf;
{
int i;
char *c, *readline();
ring -> eof=NO;
for (i=0; i<MAXSYNC; i++) {
if (ring -> eof || (c=readline(iobuf)) == NULL)
{
c=EOF;
ring -> eof=YES;
}
ring -> buf[i]=c;
}
ring -> ringp=MAXSYNC;
}
char *peep(ring,p) /*return pointer to p'th next line*/
struct aring *ring;
int p;
{
return ring -> buf[ (p - 1 + ring -> ringp) % MAXSYNC];
}
pline(c) /*print a line and free its storage space*/
char *c;
{
lineincr();
if (c != EOF) {
puts(c);
free(c);
}
else puts("--End Of File--");
putchar('\n');
}
putchar(c) /*print a printable character,
on printer too if putboth
or into report file if reporting*/
int c;
{
if (c < ' ' && (c != '\n' && c != '\r' && c != '\t')) return c;
if (c == '\n')putchar('\r');
if (putboth) {
if (c == '\t') while (++col%8) bdos(5,' ');
else {
if (c == '\n') col=0;
else col++;
bdos(5,c);
}
}
if (report) {
if (putc(c,repbuf) == ERROR) {
report=NO;
puts("Error on writing report file\n");
exit();
}
}
else bdos(2,c);
return c;
}
lineincr() /*increment line count; pause, print header
if at end of screen*/
{
if (line >= 22 && pause) {
puts("\t\t\t\t\t[Return]/Quit > ");
if (tolower(getchar()) == 'q') exit();
putchar('\n');
line=0;
}
if (!line++)printf("\t<<<<< Comparison of %s with %s >>>>>\n",
name1,name2);
}
scompare(s1,s2) /*compare strings for equality (0=same)*/
char *s1,*s2;
{
if (s1 == s2) return 0; /*both EOF*/
if (s1 == EOF || s2 == EOF) return 1;
return (white ? txtcmp(s1,s2) : strcmp(s1,s2));
}
txtcmp(s1,s2) /*compare strings, matching white space with
any white space chars*/
char *s1,*s2;
{
while (*s1 && *s2) {
if ((*s1 == ' ' || *s1 == '\t') && (*s2 == ' ' || *s2 == '\t')) {
while (*s1 == ' ' || *s1 == '\t') s1++;
while (*s2 == ' ' || *s2 == '\t') s2++;
if (!*s1 && !*s2) return 0;
}
if (*s1++ != *s2++) return 1;
}
while (*s1 == ' ' || *s1 == '\t') *s1++;
while (*s2 == ' ' || *s2 == '\t') *s2++;
return *s1-*s2;
}
search(ringa,ringb,c) /*try to get files back into sync. when mismatch
has been found. If successful, returns
number of lines to skip to get back to
synchronity, else 0*/
struct aring *ringa, *ringb;
char *c;
{
int outofsync, match, i;
if (nosync) return 0;
for (outofsync=1; outofsync < MAXSYNC; outofsync++)
/*look forward for a match*/
if (!scompare(peep(ringb,outofsync),c)) break;
/*break when found*/
if (outofsync == MAXSYNC) return 0;
else /* match found, look for sync more */
for (match=1; match < sync; match++)
if ( (i=outofsync+match) >= MAXSYNC ||
scompare(peep(ringa,match),peep(ringb,i)))
break; /*break if no match*/
if (match == sync) return outofsync;
/*return pos of start of sync matches*/
else return 0;
}
blksrch(ringa,ringb,n) /*try to get files back into sync. when mismatch
at n'th character after current
has been found. If successful, returns
number of lines to skip to get back to
synchronity, else 0*/
struct aring *ringa, *ringb;
int n;
{
int outofsync, match, i;
if (nosync) return 0;
for (outofsync=1; outofsync+n < MAXSYNC; outofsync++)
/*look forward for a match*/
if (!scompare(peep(ringb,outofsync+n),peep(ringa,n)))
break; /*break when found*/
if (outofsync == MAXSYNC) return 0;
else /* match found, look for sync more */
for (match=1; match < sync; match++)
if ( (i=outofsync+match+n) >= MAXSYNC ||
scompare(peep(ringa,match+n),peep(ringb,i)))
break; /*break if no match*/
if (match == sync) return outofsync;
/*return pos of start of sync matches*/
else return 0;
}
addr(p) /*gets a line number from a command line parameter;
returns it*/
char **p;
{
int n;
n=0;
while (*(++*p)) n=10*n+**p-'0';
return n;
}
args(argc,argv) /*read args from command line*/
int argc;
char *argv[];
{
int i;
char *p;
putboth=listing=nosync=report=NO;
pause=parity=white=YES;
start=sync=0;
stop=MAXINT;
printf("[Textcom v%d.%d]\n",VERSION/10,VERSION%10);
if (argc < 3) {
puts("Usage: TEXTCOM oldfile newfile [options]\n");
puts("\t(compares an old version of a text file with a new)\n");
puts("\n Options:\n");
puts(" -Sdd to syncronise up to dd lines\n");
printf(" (use -S for strict compare). Default = %d\n",
DEFLSYNC);
puts(" -L to list differences on printer and screen\n");
puts(" -Rname to create a file, 'name', reporting differences\n");
puts(" -C to continue without pauses at the end of each screen\n");
puts(" -Fxxxx to display differences only from ");
puts(